﻿#region File and License Information
/*
<File>
	<Copyright>Copyright © 2007, Daniel Vaughan. All rights reserved.</Copyright>
	<License see="prj:///Documentation/License.txt"/>
	<Owner Name="Daniel Vaughan" Email="dbvaughan@gmail.com"/>
	<CreationDate>2009-04-15 21:44:59Z</CreationDate>
	<LastSubmissionDate>$Date: $</LastSubmissionDate>
	<Version>$Revision: $</Version>
</File>
*/
#endregion

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Windows.Controls;

using DanielVaughan.IO;

namespace DanielVaughan.IO
{
	/// <summary>
	/// Used to invoke a file operation that works upon a file
	/// with the specified <code>fileInfo</code>.
	/// </summary>
	public delegate void FileOperationHandler(System.IO.FileInfo fileInfo);
	public delegate void MultiFileOperationHandler(IEnumerable<System.IO.FileInfo> fileInfos);
	/* TODO: [DV] Comment. */
	public delegate void SaveFileOperationHandler(string fileName, Func<System.IO.Stream> getStream);
}

namespace DanielVaughan.Services
{
	public class FileSelectionArgs
	{
		public FileSelectionArgs(IList<FileSelectionFilter> filters, int? dialogSelectedIndex)
		{
			ArgumentValidator.AssertNotNull(filters, "filters");
			this.filters = new List<FileSelectionFilter>(filters);
			if (dialogSelectedIndex.HasValue && dialogSelectedIndex + 1 > filters.Count)
			{
				throw new ArgumentOutOfRangeException("dialogSelectedIndex");
			}
			this.filterIndex = dialogSelectedIndex;
		}

		public FileSelectionArgs()
		{
			/* TODO: Make localizable resource. */
			filters = new List<FileSelectionFilter> { new FileSelectionFilter("All Files", "*.*") };
		}

		public int FilterCount
		{
			get
			{
				return filters.Count;
			}
		}

		readonly int? filterIndex;

		public int? FilterIndex
		{
			get
			{
				return filterIndex;
			}
		}

		internal string FilterString
		{
			get
			{
				StringBuilder sb = new StringBuilder();
				int filterCount = filters.Count;
				foreach (var filter in filters)
				{
					sb.Append(filter);
					if (filterCount > 1)
					{
						sb.Append('|');
					}
				}
				return sb.ToString();
			}
		}

		readonly List<FileSelectionFilter> filters;

		public IList<FileSelectionFilter> Filters
		{
			get
			{
				/* TODO: Make localizable resource. */
				return filters;
			}
		}
	}

	public class OpenFileSelectionArgs : FileSelectionArgs
	{
		public OpenFileSelectionArgs(IList<FileSelectionFilter> filters, int? dialogSelectedIndex) 
			: base(filters, dialogSelectedIndex)
		{
			/* Intentionally left blank. */
		}

		public OpenFileSelectionArgs()
		{
			/* Intentionally left blank. */
		}

		public bool MultiSelect { get; set; }

		public void SetDialogProperties(OpenFileDialog fileDialog)
		{
			ArgumentValidator.AssertNotNull(fileDialog, "fileDialog");
			fileDialog.Filter = FilterString;
			if (FilterIndex.HasValue)
			{
				fileDialog.FilterIndex = FilterIndex.Value;
			}
			fileDialog.Multiselect = MultiSelect;
		}
	}

	public class SaveFileSelectionArgs : FileSelectionArgs
	{
		public SaveFileSelectionArgs()
		{
			/* Intentionally left blank. */
		}

		public SaveFileSelectionArgs(IList<FileSelectionFilter> filters, int? dialogSelectedIndex) : base(filters, dialogSelectedIndex)
		{
			/* Intentionally left blank. */
		}

		public string FileExtension { get; set; }

		public void Populate(SaveFileDialog fileDialog)
		{
			ArgumentValidator.AssertNotNull(fileDialog, "fileDialog");
			fileDialog.Filter = FilterString;
			if (FilterIndex.HasValue)
			{
				fileDialog.FilterIndex = FilterIndex.Value;
			}
			fileDialog.DefaultExt = FileExtension;
		}
	}

	public class FileSelectionFilter
	{
		public string Name { get; private set; }
		public string FileExtension { get; private set; }

		public FileSelectionFilter(string name, string fileExtension)
		{
			Name = name;
			FileExtension = fileExtension;
		}

		public override string ToString()
		{
			return string.Format("{0}|{1}", Name, FileExtension);
		}
	}



	/// <summary>
	/// Allows for the loading and saving of file content
	/// using delegates for invocation.
	/// </summary>
	public interface IFileService
	{
		FileOperationResult SaveAs(SaveFileOperationHandler operationHandler, FileErrorAction fileErrorAction,
			SaveFileSelectionArgs fileSelectionArgs);

		FileOperationResult Save(SaveFileOperationHandler operationHandler, FileErrorAction fileErrorAction, 
			Func<Stream> getStreamFunc);

		FileOperationResult Open(FileOperationHandler operationHandler, FileErrorAction fileErrorAction, OpenFileSelectionArgs fileSelectionArgs);
		FileOperationResult Open(MultiFileOperationHandler operationHandler, FileErrorAction fileErrorAction, OpenFileSelectionArgs fileSelectionArgs);

	}
}
